package utils

/*
 +----------------------------------------------------------------------
 + Title        : configCenter
 + Author       : huwl
 + Version      : 1.0.0
 + Initial-Time : 2022-01-06
 + Last-time    : 这个文件最后修改的时间 + 修改人的名称
 + Desc         : nacos 配置中心
 +				: 文档地址: https://github.com/nacos-group/nacos-sdk-go/blob/master/README_CN.md
 +				: 插件:
 +				: 		github.com/nacos-group/nacos-sdk-go/clients
 +				: 		github.com/nacos-group/nacos-sdk-go/common/constant
 +				: 		github.com/nacos-group/nacos-sdk-go/vo
 +----------------------------------------------------------------------
*/
import (
	"fmt"
	"log"

	"github.com/nacos-group/nacos-sdk-go/clients"
	"github.com/nacos-group/nacos-sdk-go/clients/config_client"
	"github.com/nacos-group/nacos-sdk-go/model"
	"github.com/nacos-group/nacos-sdk-go/vo"
	"gopkg.in/yaml.v2"
)

// 定义NACOS配置中心结构体
type NacosConfigCenter struct {
	configClient config_client.IConfigClient
}

/**
 * 创建NACOS配置中心
 *
 * @return *EtcdConfigCenter, error
 * @author huwl
 */
func NewNacosConfigCenter() (*NacosConfigCenter, error) {
	// 创建动态配置客户端
	configClient, err := clients.NewConfigClient(
		vo.NacosClientParam{
			ClientConfig:  &NacosClientConfig,
			ServerConfigs: NacosServerConfigs,
		},
	)
	if err != nil {
		return nil, err
	}

	return &NacosConfigCenter{
		configClient: configClient,
	}, nil
}

/**
 * 获取配置数据
 *
 * @param string dataId -----------------------------------------------必传
 * @param any ConfigStruct --------------------------------------------必传
 * @param string group ------------------------------------------------必传
 * @author huwl
 */
func (cc *NacosConfigCenter) GetConfigData(dataId string, ConfigStruct any, group string) {
	// 获取配置中心数据
	content, err := cc.configClient.GetConfig(vo.ConfigParam{
		DataId: dataId,
		Group:  group,
	})
	if err != nil {
		log.Fatalf("Failed to get config: %v", err)
	}

	// yaml解析配置文件
	err = mapTo(content, ConfigStruct)
	if err != nil {
		log.Fatalf("Failed to yaml unmarshal: %v", err)
	}

	// 动态监听
	err = cc.configClient.ListenConfig(vo.ConfigParam{
		DataId: dataId,
		Group:  group,
		OnChange: func(namespace, group, dataId, data string) {
			fmt.Println("nacos watch config data: ", data)
			err = mapTo(data, ConfigStruct)
			if err != nil {
				log.Fatalf("Failed to config change: %v", err)
			} else {
				// 在这里更新配置，比如重新初始化数据库连接等
				switch dataId {
				case RedisConfigCenter:
					// 重新初始化 redis 连接
					ResetRedisInstance()
				case MongoConfigCenter:
					CloseMongo()
				case EsConfigCenter:
					CloseElasticSearch()
				}
			}
		},
	})
	if err != nil {
		log.Fatalf("Failed to listen config: %v", err)
	}

	log.Println("nacos config center success")
}

/**
 * 发布配置
 *
 * @param string dataId -----------------------------------------------必传
 * @param string group ------------------------------------------------必传
 * @param string content ----------------------------------------------必传
 * @return bool, error
 * @author huwl
 */
func (cc *NacosConfigCenter) NacosPublishConfig(dataId, group, content string) (bool, error) {
	return cc.configClient.PublishConfig(vo.ConfigParam{
		DataId:  dataId,
		Group:   group,
		Content: content,
	})
}

/**
 * 删除配置
 *
 * @param string dataId --------------------------------------必传
 * @param string group ---------------------------------------必传
 * @return bool, error
 * @author huwl
 */
func (cc *NacosConfigCenter) NacosDeleteConfig(dataId, group string) (bool, error) {
	return cc.configClient.DeleteConfig(vo.ConfigParam{
		DataId: dataId,
		Group:  group,
	})
}

/**
 * 获取配置
 *
 * @param string dataId --------------------------------------必传
 * @param string group ---------------------------------------必传
 * @return string, error
 * @author huwl
 */
func (cc *NacosConfigCenter) NacosGetConfig(dataId, group string) (string, error) {
	return cc.configClient.GetConfig(vo.ConfigParam{
		DataId: dataId,
		Group:  group,
	})
}

/**
 * 取消监听配置
 *
 * @param string dataId --------------------------------------必传
 * @param string group ---------------------------------------必传
 * @return error
 * @author huwl
 */
func (cc *NacosConfigCenter) NacosCancelListenConfig(nacosConfigClient config_client.IConfigClient, dataId, group string) error {
	return cc.configClient.CancelListenConfig(vo.ConfigParam{
		DataId: dataId,
		Group:  group,
	})
}

/**
 * 获取配置
 *
 * @param string searchParams --------------------------------必传
 * @param string dataId --------------------------------------必传
 * @param string group ---------------------------------------必传
 * @param int pageNo -----------------------------------------必传
 * @param int pageSize ---------------------------------------必传
 * @return *model.ConfigPage, error
 * @author huwl
 */
func (cc *NacosConfigCenter) NacosSearchConfig(nacosConfigClient config_client.IConfigClient, searchParams, dataId, group string, pageNo, pageSize int) (*model.ConfigPage, error) {
	return cc.configClient.SearchConfig(vo.SearchConfigParam{
		Search:   searchParams,
		DataId:   dataId,
		Group:    group,
		PageNo:   pageNo,
		PageSize: pageSize,
	})
}

/**
 * 反序列化
 *
 * @param string content -------------------------------------必传
 * @param any ConfigStruct -----------------------------------必传
 * @return error
 * @author huwl
 */
func mapTo(content string, ConfigStruct any) error {
	return yaml.Unmarshal([]byte(content), ConfigStruct)
}
